#pragma once  // 防止头文件重复包含

// 包含必要的头文件
#include <iostream>
#include <time.h>      // 时间相关
#include <stdarg.h>    // 可变参数
#include <sys/types.h> // 系统调用相关
#include <sys/stat.h>
#include <fcntl.h>     // 文件操作
#include <unistd.h>
#include <stdlib.h>

#define SIZE 1024  // 缓冲区大小

// 定义日志级别
#define Info 0
#define Debug 1
#define Warning 2
#define Error 3
#define Fatal 4

// 定义日志输出方式
#define Screen 1      // 输出到屏幕
#define Onefile 2     // 输出到单个文件
#define Classfile 3   // 根据日志级别输出到不同文件

#define LogFile "log.txt"  // 默认日志文件名

class Log
{
public:
    // 构造函数：初始化输出方式为屏幕输出，设置默认日志路径
    Log()
    {
        printMethod = Screen;
        path = "./log/";
    }

    // 设置日志输出方式
    void Enable(int method)
    {
        printMethod = method;
    }

    // 将日志级别转换为对应的字符串
    std::string levelToString(int level)
    {
        switch (level)
        {
        case Info:
            return "Info";
        case Debug:
            return "Debug";
        case Warning:
            return "Warning";
        case Error:
            return "Error";
        case Fatal:
            return "Fatal";
        default:
            return "None";
        }
    }

    // 根据不同的输出方式打印日志
    void printLog(int level, const std::string &logtxt)
    {
        switch (printMethod)
        {
        case Screen:
            std::cout << logtxt << std::endl;
            break;
        case Onefile:
            printOneFile(LogFile, logtxt);
            break;
        case Classfile:
            printClassFile(level, logtxt);
            break;
        default:
            break;
        }
    }

    // 将日志写入指定文件
    void printOneFile(const std::string &logname, const std::string &logtxt)
    {
        std::string _logname = path + logname;
        // 以追加方式打开文件，如果不存在则创建
        int fd = open(_logname.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666);
        if (fd < 0)
            return;
        write(fd, logtxt.c_str(), logtxt.size());
        close(fd);
    }

    // 根据日志级别将日志写入不同文件
    void printClassFile(int level, const std::string &logtxt)
    {
        std::string filename = LogFile;
        filename += ".";
        filename += levelToString(level); // 例如："log.txt.Debug"
        printOneFile(filename, logtxt);
    }

    ~Log()
    {
    }

    // 重载操作符()，实现格式化日志输出
    void operator()(int level, const char *format, ...)
    {
        // 获取当前时间
        time_t t = time(nullptr);
        struct tm *ctime = localtime(&t);
        
        // 构造日志前缀（时间戳和日志级别）
        char leftbuffer[SIZE];
        snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", 
                levelToString(level).c_str(),
                ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
                ctime->tm_hour, ctime->tm_min, ctime->tm_sec);

        // 处理可变参数，构造日志内容
        va_list s;
        va_start(s, format);
        char rightbuffer[SIZE];
        vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
        va_end(s);

        // 组合完整日志文本
        char logtxt[SIZE * 2];
        snprintf(logtxt, sizeof(logtxt), "%s %s", leftbuffer, rightbuffer);

        // 输出日志
        printLog(level, logtxt);
    }

private:
    int printMethod;        // 日志输出方式
    std::string path;      // 日志文件路径
};

Log lg;  // 创建全局日志对象